/*
 *    Copyright © OpenAtom Foundation.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.inspur.edp.cef.designtime.api.entity.increment.merger;

import com.inspur.edp.cef.designtime.api.IGspCommonField;
import com.inspur.edp.cef.designtime.api.changecontrolrule.controlrule.basic.AbstractControlRule;
import com.inspur.edp.cef.designtime.api.changecontrolrule.controlrule.cm.CommonDataTypeControlRule;
import com.inspur.edp.cef.designtime.api.changecontrolrule.controlrule.cm.CommonFieldControlRule;
import com.inspur.edp.cef.designtime.api.changecontrolrule.controlruledef.cm.CommonDataTypeControlRuleDef;
import com.inspur.edp.cef.designtime.api.changecontrolrule.controlruledef.cm.CommonFieldContrulRuleDef;
import com.inspur.edp.cef.designtime.api.collection.GspFieldCollection;
import com.inspur.edp.cef.designtime.api.element.increment.AddedFieldIncrement;
import com.inspur.edp.cef.designtime.api.element.increment.GspCommonFieldIncrement;
import com.inspur.edp.cef.designtime.api.element.increment.merger.CommonFieldIncrementMerger;
import com.inspur.edp.cef.designtime.api.entity.GspCommonDataType;
import com.inspur.edp.cef.designtime.api.entity.GspCommonField;
import com.inspur.edp.cef.designtime.api.entity.increment.CommonEntityIncrement;
import com.inspur.edp.cef.designtime.api.entity.increment.ModifyEntityIncrement;
import com.inspur.edp.cef.designtime.api.increment.IncrementType;
import com.inspur.edp.cef.designtime.api.increment.merger.AbstractIncrementMerger;
import com.inspur.edp.cef.designtime.api.increment.merger.MergeUtils;
import com.inspur.edp.cef.designtime.api.increment.property.BooleanPropertyIncrement;
import com.inspur.edp.cef.designtime.api.increment.property.ObjectPropertyIncrement;
import com.inspur.edp.cef.designtime.api.increment.property.PropertyIncrement;
import com.inspur.edp.cef.designtime.api.increment.property.StringPropertyIncrement;
import com.inspur.edp.cef.designtime.api.json.CefNames;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import lombok.var;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class DataTypeIncrementMerger extends AbstractIncrementMerger {

    protected boolean includeAll;

    public DataTypeIncrementMerger() {
    }
    private static Logger logger = LoggerFactory.getLogger(DataTypeIncrementMerger.class);
    public DataTypeIncrementMerger(boolean includeAll) {
        this.includeAll = includeAll;
    }

    public GspCommonDataType merge(
            GspCommonDataType extendDataType,
            GspCommonDataType rootDataType,
            CommonEntityIncrement extendIncrement,
            CommonEntityIncrement baseIncrement,
            CommonDataTypeControlRule rule,
            CommonDataTypeControlRuleDef def) {

        if (baseIncrement.getIncrementType() == IncrementType.Modify)
            return mergeModifyIncrement(extendDataType,rootDataType, (ModifyEntityIncrement) extendIncrement, (ModifyEntityIncrement) baseIncrement, rule, def);
        return null;
    }


    private GspCommonDataType mergeModifyIncrement(
            GspCommonDataType extendDataType,
            GspCommonDataType rootDataType,
            ModifyEntityIncrement extendIncrement,
            ModifyEntityIncrement baseIncrement,
            CommonDataTypeControlRule rule,
            CommonDataTypeControlRuleDef def) {

        var propChanges = baseIncrement.getChangeProperties();
        if (propChanges.size() > 0) {
            mergeChangeProps(extendDataType, extendIncrement.getChangeProperties(), propChanges, rule, def);
        }

        var fieldChanges = baseIncrement.getFields();
        if (fieldChanges.size() > 0) {
            mergeFieldProps(extendDataType,rootDataType, extendIncrement.getFields(), fieldChanges, rule, def);
        }

        mergeExtendModifyIncrement(extendDataType,rootDataType, extendIncrement, baseIncrement, rule, def);

        return extendDataType;
    }

    private void mergeChangeProps(
            GspCommonDataType extendDataType,
            HashMap<String, PropertyIncrement> extendIncrement,
            HashMap<String, PropertyIncrement> baseIncrement,
            CommonDataTypeControlRule rule,
            CommonDataTypeControlRuleDef def) {

        if(includeAll){
            mergeAllChange(extendDataType, extendIncrement, baseIncrement);
            return;
        }
        if (baseIncrement.containsKey(CefNames.Name)) {
            String mergedName = MergeUtils.getStringValue(
                    CefNames.Name,
                    (StringPropertyIncrement) baseIncrement.get(CefNames.Name),
                    extendIncrement,
                    rule.getNameControlRule(),
                    def.getNameControlRule());
            extendDataType.setName(mergedName);
        }
    }

    private void mergeAllChange(
            GspCommonDataType extendDataType,
            HashMap<String, PropertyIncrement> extendIncrement,
            HashMap<String, PropertyIncrement> baseIncrement) {
        for (var incrementPair : baseIncrement.entrySet()) {
            String key = incrementPair.getKey();
            PropertyIncrement increment = incrementPair.getValue();
            dealChangeProp(extendDataType, extendIncrement, key, increment);
        }
    }

    private void dealChangeProp(GspCommonDataType extendDataType, HashMap<String, PropertyIncrement> extendIncrement, String key, PropertyIncrement increment) {
        switch (key){
            case CefNames.Name:
                String mergedName = MergeUtils.getStringValue(CefNames.Name, (StringPropertyIncrement)increment, extendIncrement, null,null);
                extendDataType.setName(mergedName);
                return;
            case CefNames.Code:
                String mergedCode = MergeUtils.getStringValue(CefNames.Code, (StringPropertyIncrement)increment, null, null,null);
                extendDataType.setCode(mergedCode);
                return;
            case CefNames.IsRef:
                boolean mergedIsRef = MergeUtils.getBooleanValue(CefNames.IsRef, (BooleanPropertyIncrement)increment, null, null,null);
                extendDataType.setIsRef(mergedIsRef);
                return;
            case CefNames.I18nResourceInfoPrefix:
                String mergedI18n = MergeUtils.getStringValue(CefNames.I18nResourceInfoPrefix, (StringPropertyIncrement)increment, null, null,null);
                extendDataType.setI18nResourceInfoPrefix(mergedI18n);
                return;
            case CefNames.BeLabel:
                List<String> mergedBeLabel = MergeUtils.getObjectValue(CefNames.BeLabel, (ObjectPropertyIncrement)increment, null, null,null);
                extendDataType.setBeLabel(mergedBeLabel);
                return;
        }
        dealExtendChangeProp(extendDataType, extendIncrement, key, increment);
    }

    protected void dealExtendChangeProp(GspCommonDataType extendDataType, HashMap<String, PropertyIncrement> extendIncrement, String key, PropertyIncrement increment){

    }

    private void mergeFieldProps(
            GspCommonDataType extendDataType,
            GspCommonDataType rootDataType,
            HashMap<String, GspCommonFieldIncrement> extendIncrement,
            HashMap<String, GspCommonFieldIncrement> baseIncrement,
            CommonDataTypeControlRule rule,
            CommonDataTypeControlRuleDef def) {
        StringBuilder builder=new StringBuilder();
        builder.append("开始同步编号为：").append(extendDataType.getCode()).append(",名称为：").append(extendDataType.getName()).append("的节点对象上的字段信息");
        logger.error(builder.toString());
        logger.error("同步的字段数量："+baseIncrement.size());
        for (var fieldPair : baseIncrement.entrySet()) {

            var fieldIncrement = fieldPair.getValue();
            switch (fieldIncrement.getIncrementType()) {
                case Added:
                    var baseAddedField = ((AddedFieldIncrement) fieldIncrement).getAddedField();
                    dealAddedField(baseAddedField, extendIncrement);
                    //todo 字段列表中已有相同Id的字段时，不再添加
                    if (isAddNewField(extendDataType,baseAddedField)) {
                        extendDataType.getContainElements().add(baseAddedField);
                    }
                    break;
                case Deleted:
                    extendDataType.getContainElements().remove(fieldIncrement.getId());
                    break;
                case Modify:
                    dealModifyField(extendDataType,rootDataType, fieldIncrement, extendIncrement, rule, def);
            }

        }

    }
    private boolean isAddNewField(GspCommonDataType extendDataType, IGspCommonField field) {
        GspFieldCollection containElements = extendDataType.getContainElements();
        IGspCommonField commonField=getCommonField(containElements,field.getID());
        if(commonField!=null){
            logger.error("当前名称为："+extendDataType.getName()+"的节点对象上已经存在ID为："+field.getID()+"的字段！");
        }
         return commonField==null;
    }
    private IGspCommonField getCommonField(GspFieldCollection containElements , String fieldId){
        for (IGspCommonField commonField:containElements){
            if(fieldId.equals(commonField.getID()))
                return commonField;
        }
        return null;
    }
    private void dealAddedField(GspCommonField field, HashMap<String, GspCommonFieldIncrement> extendIncrement) {

        //todo 同编号，同标签字段的处理策略
    }

    private void dealModifyField(
            GspCommonDataType extendDataType,
            GspCommonDataType rootDataType,
            GspCommonFieldIncrement baseFieldIncrement,
            HashMap<String, GspCommonFieldIncrement> extendIncrement,
            CommonDataTypeControlRule rule,
            CommonDataTypeControlRuleDef def) {
        var field = extendDataType.findElement(baseFieldIncrement.getId());
        if (field == null) {
            if (rootDataType != null) {
                IGspCommonField rootField = rootDataType.findElement(baseFieldIncrement.getId());
                if (rootField != null)
                    field = rootField.clone(extendDataType, null);
            }
            if (field == null)
                throw new RuntimeException("节点" + extendDataType.getCode() + "上没有找到字段" + baseFieldIncrement.getId());
        }
        GspCommonFieldIncrement extendFieldIncrement = null;
        if (extendIncrement.containsKey(baseFieldIncrement.getId()))
            extendFieldIncrement = extendIncrement.get(baseFieldIncrement.getId());
        var merger = getFieldMerger();
        CommonFieldContrulRuleDef fieldContrulRuleDef = (CommonFieldContrulRuleDef) def.getChildControlRules().get(CefNames.Element);
        Map<String, AbstractControlRule> elementRules = rule.getChildRules().get(CefNames.Element);
        CommonFieldControlRule fieldRule = (CommonFieldControlRule) elementRules.get(field.getID());
        field = merger.merge((GspCommonField) field, extendFieldIncrement, baseFieldIncrement, fieldRule, fieldContrulRuleDef);

    }

    protected CommonFieldIncrementMerger getFieldMerger() {
        return new CommonFieldIncrementMerger(includeAll);
    }

    protected void mergeExtendModifyIncrement(
            GspCommonDataType extendDataType,
            GspCommonDataType rootDataType,
            ModifyEntityIncrement extendIncrement,
            ModifyEntityIncrement baseIncrement,
            CommonDataTypeControlRule rule,
            CommonDataTypeControlRuleDef def) {

    }
}
